package com.tinkerapps.protocols.ssdp;

/**
 * Class for parsing SSDP responses
 */
public final class SSDPResponse {

	/**
	 * Constants
	 */
	
	private final static String HTTP_OK = "HTTP/1.1 200 OK";
	private final static String NOTIFY = "NOTIFY * HTTP/1.1";
	private final static String NEW_LINE = "\r\n";
	private final static String HEADER_LOCATION = "LOCATION:";
	private final static String HEADER_NOTIFICATION_SUBTYPE = "NTS:";
	private final static String HEADER_UNIQUE_SERVICE_NAME = "USN:";
	private final static String NOTIFICATION_SUBTYPE_VALUE_BYEBYE = "ssdp:byebye";
	private final static String NOTIFICATION_SUBTYPE_VALUE_ALIVE = "ssdp:alive";
	
	/**
	 * Check if given message is a response message (vs notify message)  
	 * @param message Message to check
	 * @return true if response message; false otherwise
	 */
	public static boolean isResponse(String message) {
		if (message == null)
			throw new IllegalArgumentException("argument 'message' is null");
		return message.startsWith(HTTP_OK);
	}

	/**
	 * Check if given message is a response message (vs notify message)  
	 * @param message Message to check
	 * @return true if response message; false otherwise
	 */
	public static boolean isNotify(String message) {
		if (message == null)
			throw new IllegalArgumentException("argument 'message' is null");
		return message.startsWith(NOTIFY);
	}
	
	/**
	 * Extract header from response
	 * @param response Response data
	 * @param header Header to extract
	 * @return Extracted header or null if header is not present
	 */
	private static String getHeader(String response, String header) {
		if (response == null)
			throw new IllegalArgumentException("argument 'response' is null");
		if (header == null)
			throw new IllegalArgumentException("argument 'header' is null");
		
		int startIdx = response.toUpperCase().indexOf(header.toUpperCase());
		int endIdx = -1;
		
		if (startIdx == -1)
			return null;
		endIdx = response.indexOf(NEW_LINE, startIdx + header.length());
		if (endIdx == -1)
			endIdx = response.length();
		return response.substring(startIdx + header.length(), endIdx).trim();
	}
	
	/**
	 * Extract location URL from response
	 * @param response Response data
	 * @return Extracted location URL or null if location URL is not present
	 */
	public static String getLocationURL(String response) {
		return getHeader(response, HEADER_LOCATION);
	}
	
	/**
	 * Extract notification subtype from response
	 * @param response Response data
	 * @return Extracted notification subtype or null if not present
	 */
	private static String getNotificationSubType(String response) {
		return getHeader(response, HEADER_NOTIFICATION_SUBTYPE);
	}

	/**
	 * Determine if given response contains notification subtype corresponding to 'byebye' notification
	 * @param response Response data
	 * @return true if 'byebye' notification; false otherwise
	 */
	public static boolean isByeByeNotification(String response) {
		String subtype = getNotificationSubType(response);
		
		return (subtype != null && subtype.equals(NOTIFICATION_SUBTYPE_VALUE_BYEBYE));
	}

	/**
	 * Determine if given response contains notification subtype corresponding to 'alive' notification
	 * @param response Response data
	 * @return true if 'alive' notification; false otherwise
	 */
	public static boolean isAliveNotification(String response) {
		String subtype = getNotificationSubType(response);
		
		return (subtype != null && subtype.equals(NOTIFICATION_SUBTYPE_VALUE_ALIVE));
	}
	
	/**
	 * Get device ID from notification response
	 * @param response Response data (should be notification response)
	 * @return Extracted device ID or null if not present (i.e. not notification response)
	 */
	public static String getDeviceId(String response) {
		String uniqueServiceName = getHeader(response, HEADER_UNIQUE_SERVICE_NAME);
		
		if (uniqueServiceName == null)
			return null;
		if (!uniqueServiceName.toLowerCase().startsWith("uuid:"))
			return null;
		int startIdx = uniqueServiceName.indexOf(':');
		int endIdx = -1;
		
		if (startIdx == -1)
			return null;
		endIdx = uniqueServiceName.indexOf(':', startIdx + 1);
		if (endIdx == -1)
			endIdx = uniqueServiceName.length();
		return uniqueServiceName.substring(startIdx + 1, endIdx);
	}
}
